local log = require("mylog")
-- 加载全局queue资源
_G.mqtt_queue = dx_map.get(_G_map, "mqtt_queue")
local dx_map = require("dx_map")
local dx_bit = require("dx_bit")
local gpio = require("dx_gpio")
local channel = require("channel")
local dx_channel = require("dx_channel")
local string_util = require("string_util")
local config = require("config")
local dx_json = require("dx_json")
local time = require("time")
local os_util = require("os_util")
local dx_queue = require("dx_queue")
local serialport_service = require("serialport_service")
require("update_config")
local serialport = {}

-- 加载全局map资源
local _G_map = _G["_G_map"]

_G.channel_read_queue = dx_map.get(_G_map, "channel_read_queue")
_G.channel_write_queue = dx_map.get(_G_map, "channel_write_queue")
-- 加载全局sqlite实例
_G.sqlite_client = dx_map.get(_G_map, "sqlite_client")

-- 定义相关命令头和命令字
PRO_HEAD1 = "55"
PRO_HEAD2 = "AA"
PRO_CMD_04 = "04"
PRO_HEAD_NUM1 = 0x55
PRO_HEAD_NUM2 = 0xAA
-- 串口返回数据结果cmd
PROTOCOL_CMD_GET_SCAN_RESULT_2 = "33"

BASE_PATH = "/dev/ttyS0"
VBAR_NORMAL_STR = "0"

-- 初始化读取配置信息！(所有require("update_config")的.lua文件都需要从线程中读取配置，每次修改都需要覆盖Map中的配置，且需要保证同一时间只能有一个线程操作该键值对)
while true do
    if dx_map.get(_G_map, "g_config_str") ~= nil and dx_map.get(_G_map, "vbar_config_t_str") ~= nil then
        local g_config_str = dx_map.get(_G_map, "g_config_str")
        local vbar_config_t_str = dx_map.get(_G_map, "vbar_config_t_str")
        g_config = dx_json.decode(g_config_str)
        vbar_config_t = dx_json.decode(vbar_config_t_str)
        break
    end
    time.sleep(0.01)
end
log.debug("[串口信道]打印从_G_map中读取的g_config表", dx_json.encode(g_config))

-- 监听信道，处理接收到的数据
_G.serial_port_listen = function()
    -- 定义接收串口数据的结构体
    local pack = {}

    while true do
        pack = serialport.vg_pro_recv_pack(vbar_channel, pack)
        if pack ~= nil then
            serialport.parse_pack(pack)
        end
        pack = nil
        os.execute("sleep 1")
    end
end

function serialport.vg_pro_recv_pack1(vbar_channel, size)
    -- local buffer = channel.recv(vbar_channel, size, 30)
    local buffer = dx_channel.read(channel_read_queue, size)
    -- print(buffer)
    return buffer
end

-- 监听串口，接收数据包
function serialport.vg_pro_recv_pack(vbar_channel)
    local pack = {}
    local ret = 0

    -- 用于接收每次从信道中接受的数据，一般是4char
    local buffer = ""

    -- 判断数据头部是不是以55 AA开头
    local flag = serialport.is_pack_head(vbar_channel, 300)
    if flag ~= true then
        return nil
    end
    pack["head"] = {}
    table.insert(pack["head"], PRO_HEAD1)
    table.insert(pack["head"], PRO_HEAD2)
    -- pack["head"][0] = PRO_HEAD1
    -- pack["head"][1] = PRO_HEAD2

    -- 接收信道数据(cmd, 数据长度等元数据)，上面已经判断过可以接受数据了，即前两个字节是：0x55 0xAA
    local buffer = serialport.vg_pro_recv_pack1(vbar_channel, 4)
    if buffer == nil then
        return nil
    end
    log.debug("buffer:")
    log.debug(buffer)

    local split = dx_bit.split(buffer, ",")

    local data_size
    for k, v in pairs(split) do
        if k == 1 then
            pack["cmd"] = v
        elseif k == 2 then
            pack["result"] = v
        elseif k == 3 then
            data_size = dx_bit.xstr_to_dec_num(v, 16)
        elseif k == 4 then
            pack["dlen"] = dx_bit.xstr_to_dec_num(v, 16) + data_size
        end
    end
    log.debug("[串口输入]读取数据长度：", pack["dlen"])
    if pack["dlen"] <= 0 then
        return nil
    end

    pack["data"] = ""
    pack["crc"] = ""

    -- 接收基本数据，填充pack["data"]。这里数据接收长度为什么是pack["dlen"] + 1呢？因为最开始的1字节是校验位，校验是QR还是NFC
    pack["data"] = serialport.vg_pro_recv_pack1(vbar_channel, pack["dlen"])
    -- log.debug("[串口输入]读取数据内容（未格式化）：", pack["data"])
    pack["metadata"] = pack["data"]
    -- 接收尾部1字节的校验位，进行校验
    pack["crc"] = serialport.vg_pro_recv_pack1(vbar_channel, 1)
    log.debug("[串口输入]读取校验位：", pack["crc"])

    -- 校验尾部1字节的校验位
    local validSuccess = serialport.is_valid_pack(pack)

    -- 走进这个逻辑表明校验失败，返回空
    if validSuccess ~= true then
        return nil
    end

    local str = ""
    -- 获取数据域1字节的数据类型type 1xh:二维码数据  4xh:NFC卡  8xh:蓝牙数据  axh:按键
    for k, v in pairs(dx_bit.split(pack["data"], ",")) do
        if k == 1 then
            -- 字符串转换为对应的数字，例如：字符串"11"转换为16进制0x11,对应十进制17
            pack["typeHex"] = dx_bit.xstr_to_dec_num(v, 16)
        end
        str = str .. dx_bit.from_hex(v)
    end
    pack["data"] = str
    log.debug("[串口输入]读取数据内容：", pack["data"])
    return pack
end

-- 该方法直到读到55AA标识符才跳出循环
function serialport.is_pack_head(vbar_channel, timeout)
    local flag = false
    local buffer = ""
    -- 循环读取命令头55标识
    while buffer ~= PRO_HEAD1 do
        buffer = serialport.vg_pro_recv_pack1(vbar_channel, 1)
        dx_map.set(_G_map, "serialport_dog", "Y")
    end

    -- 循环读取命令头AA标识
    local isBreak = false
    while true do
        while buffer ~= PRO_HEAD2 do
            buffer = serialport.vg_pro_recv_pack1(vbar_channel, 1)
            log.debug("[串口输入", BASE_PATH, "]读取第二个命令头：", buffer)
            if buffer == "" then
                isBreak = true
                break
            end
            if buffer ~= "" and PRO_HEAD1 == buffer then
                -- 仅仅退出内层循环，相当于continue
                isBreak = false
                break
            elseif buffer ~= "" and PRO_HEAD2 == buffer then
                flag = true
                isBreak = true
                break
            end
        end
        if isBreak == true then
            break
        end
    end
    return flag
end

-- 校验尾部1字节的校验位
function serialport.is_valid_pack(pack)
    local cmd = dx_bit.xstr_to_dec_num(pack["cmd"], 16)
    local resutlNum = 0
    -- local resutlNum = dx_bit.xstr_to_dec_num(pack["result"], 16)
    -- local dlen = dx_bit.xstr_to_dec_num(pack["dlen"], 10)
    local dlen = pack["dlen"]
    local crc = cmd
    if pack["crc"] ~= nil or pack["crc"] ~= "" then
        local dataArray = dx_bit.split(pack["data"], ",")

        crc = bit.bxor(crc, PRO_HEAD_NUM1)
        crc = bit.bxor(crc, (bit.band(bit.rshift(dlen, 0), 0xff)))

        crc = bit.bxor(crc, PRO_HEAD_NUM2)
        crc = bit.bxor(crc, (bit.band(bit.rshift(dlen, 8), 0xff)))
        for i, v in ipairs(dataArray) do
            local num = dx_bit.xstr_to_dec_num(v, 16)
            crc = bit.bxor(crc, num)
        end
        local hexCrc = dx_bit.xstr_to_dec_num(pack["crc"], 16)
        crc = bit.bxor(crc, resutlNum)
        log.debug("传入的校验位：", hexCrc, "正确的校验位：" .. crc)
        if crc ~= hexCrc then
            return false
        end
    else
        return false
    end
    return true
end

function serialport.parse_pack(pack)
    print("=========================")
    print(dx_json.encode(pack))
    if pack["result"] == VBAR_NORMAL_STR then
        -- 解析数据
        pack["timestamp"] = time.getNowTime()
        pack["dlen"] = pack["dlen"] - 1
        if bit.band(pack["typeHex"], 0x40) == 0x40 then
            -- 卡
            print("走卡")
            serialport_service.card(pack)
        elseif bit.band(pack["typeHex"], 0x10) == 0x10 then
            -- 二维码
            print("走二维码")
            serialport_service.qr_code(pack)
        elseif bit.band(pack["typeHex"], 0x80) == 0x80 then
            -- 蓝牙
            print("走蓝牙")
            serialport_service.bluetooth(pack)
        end
    else
        -- 失败：执行失败动作
        log.debug("[串口输入]串口数据返回失败")
    end
end

serial_port_listen()

return serialport
